﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Diagnostics;
using DFASimulation;

namespace DFAGuiApplication
{
    public partial class Form1 : Form
    {
        List<List<String>> transitions;
        List<String> rules;
        List<String> accept;
        List<String> stateNames;
        List<String> stateIds;
        String[] S;
        String[] F;
        String Path;
        DFAInterface dfainterface;
        Form2 formG;

        public Form1()
        {
            InitializeComponent();
            dfainterface = new DFAInterface(false);
        }

        private void button1_Click(object sender, EventArgs e)
        {
            getSetStates();
            getSetRules();
        }

        private void button2_Click(object sender, EventArgs e)
        {
            statesTableView.Rows.Add();
        }


        private void button4_Click(object sender, EventArgs e)
        {
            getSetTransitions();
            getSetAcceptStates();
        }

        private void getSetAcceptStates()
        {
            if (String.IsNullOrEmpty(textBox1.Text))
            {
                MessageBox.Show("No accept states where set, errors may occur", "Deterministc Finite Automata Simulation Error");
                return;
            }
            F = textBox1.Text.Split(new char[] { ',' });
            accept = new List<string>(F.Length);
            for (int i = 0; i < accept.Capacity; i++)
            {
                accept.Add(F[i]);
            }
            if (!dfainterface.createAcceptStates(accept))
            {
                MessageBox.Show("Failed to set accept states, errors may occur", "Deterministc Finite Automata Simulation Error");
            }
        }

        private void getSetStates()
        {
            stateIds = new List<String>();
            stateNames = new List<String>();
            for (int i = 0; i < statesTableView.Rows.Count-1; i++)
            {
                stateIds.Add(statesTableView.Rows[i].Cells[0].Value.ToString());
                stateNames.Add(statesTableView.Rows[i].Cells[1].Value.ToString());
            }
            dfainterface.createStates(stateNames, stateIds);
        }

        private void getSetTransitions()
        {
            transitions = new List<List<String>>();
            for (int i = 0; i < transitionsTableView.Rows.Count - 1; i++)
            {
                DataGridViewRow row = transitionsTableView.Rows[i];
                transitions.Add(new List<String>());
                for (int j = 0; j < S.Length; j++)
                {
                    transitions[i].Add(row.Cells[j].Value.ToString());
                }
            }
            dfainterface.createTransitions(transitions);
        }

        private void getSetRules()
        {
            if (String.IsNullOrEmpty(textBoxS.Text)) return; 
            S = textBoxS.Text.Split(new char[] { ',' });
            rules = new List<string>(S.Length);
            for (int i = 0; i < S.Length; i++)
            {
                rules.Add(S[i]);
            }
            transitionsTableView.Columns.Clear();
            foreach (var rule in rules)
                transitionsTableView.Columns.Add(new DataGridViewTextBoxColumn() { HeaderText = rule });
            dfainterface.createRules(rules);
        }

        private void button2_Click_1(object sender, EventArgs e)
        {
            try
            {
                dfainterface.setStartState(int.Parse(statesTableView.SelectedRows[0].Cells[0].Value.ToString()));
            }
            catch
            {
                MessageBox.Show("Please select a state to use as the graph start", "Deterministc Finite Automata Simulation Error");
                return;
            }
            dfainterface.D(textBox2.Text);
            textBox3.Text = ((DFAState)dfainterface.finalState).id + ":" + ((DFAState)dfainterface.finalState).desc;
            if (dfainterface.validateSimulation())
            {
                textBox3.BackColor = Color.GreenYellow;
            }
            else
            {
                textBox3.BackColor = Color.OrangeRed;
            }
            createGraphPath();
            textBoxPath.Text = Path;
        }

        private void createGraphPath()
        {
            Path = dfainterface.startState.id + "->";
            DFAState dummy = dfainterface.startState;
            foreach (var s in textBox2.Text)
            {
                dummy = dfainterface.DOf(s.ToString(), dummy);
                Path += dummy.id + "->";
            }
            Path = Path.TrimEnd(new char[] { '-', '>' });
        }

        private void linkLabel1_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {

            Process.Start("http://en.wikipedia.org/wiki/State_(computer_science)");
        }

        private void linkLabel2_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            Process.Start("http://en.wikipedia.org/wiki/Function_(mathematics)");
        }

        private void linkLabel3_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            Process.Start("http://en.wikipedia.org/wiki/Alphabet_(computer_science)");
        }

        private void linkLabel4_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            Process.Start("http://en.wikipedia.org/wiki/Finite_state_machine#Accept_state");
        }
        
        private void button3_Click(object sender, EventArgs e)
        {
            try
            {
                dfainterface.setStartState(int.Parse(statesTableView.SelectedRows[0].Cells[0].Value.ToString()));
            }
            catch
            {
                MessageBox.Show("Please select a state to use as the graph start", "Deterministc Finite Automata Simulation Error");
                return;
            }
            if (formG != null)
                formG.Dispose();
                if (stateNames.Count > 0 && stateIds.Count > 0 && transitions.Count > 0)
                    formG = new Form2(dfainterface);
                //formG = new Form2(stateNames, stateIds, transitions);
                else
                    formG = new Form2();
                formG.Show();
        }

    }
}
